/**
 * 用户相关路由处理模块
 * @author HalRui
 * @version 1.0.0
 * @description 处理用户注册、登录、邮箱验证、验证码发送等相关API路由
 * @date 2025年9月27日
 */

// 引入Express框架，用于创建Web应用和API
const express = require('express');
// 创建Express路由实例，用于定义各种HTTP请求的处理函数
const router = express.Router();
// 引入用户信息操作API模块，提供用户数据的增删改查功能
const userinfosAPI = require("../../libs/userinfos-api");
// 引入邮箱验证中间件，用于验证邮箱格式的合法性
const emailValidator = require("../../middlewares/email-validator-middleware");
// 引入工具服务模块，提供验证码生成、邮件发送等辅助功能
const toolService = require("../../utils/tool-service");
// 引入Redis操作API模块，用于缓存验证码、令牌等数据
const redisAPI = require("../../libs/redis-api");
// 引入SVG验证码生成库，用于创建图形验证码
const svgCaptcha = require("svg-captcha");
// 引入UUID生成函数，用于创建唯一标识符
const { v4: uuidv4 } = require('uuid');
// 引入JWT库，用于生成和验证JSON Web令牌
const jwt = require("jsonwebtoken");
// 引入环境配置文件，包含数据库连接、JWT密钥等配置信息
const config = require("../../env.config.json");
// 引入状态码常量模块，统一定义API返回的状态码和消息文本
const STATUS_CODES = require("../../utils/status-codes");

// 定义获取图形验证码路由 - GET /captcha
// 返回SVG格式的数学公式验证码图片，用于登录验证
router.get('/captcha', async (req, res) => {
    try {
        // 1. 从请求头中获取UUID，用于标识不同的验证码会话
        const uuidHead = req.get("uuid");

        console.log("🔍 请求头中的UUID:", uuidHead);
        console.log("🍪 请求中的cookies:", req.cookies);
        
        // 2. 生成数学公式验证码
        // 配置验证码参数：长度、字符集、干扰项、颜色等
        const captcha = svgCaptcha.createMathExpr({
            size: 6,                    // 验证码长度（6位）
            ignoreChars: '0o1iIOlL',    // 忽略容易混淆的字符（0、o、1、i、I、O、l、L）
            noise: 4,                   // 干扰线条数量
            color: true,                // 启用彩色验证码
            background: '#f0f0f0',      // 设置背景色为浅灰色
            mathMin: 1,                 // 数学表达式的最小值
            mathMax: 9,                 // 数学表达式的最大值
            mathOperator: '+-'          // 限制运算符类型为加法和减法
        });

        let setResult;  // 存储验证码保存结果
        if(uuidHead){   // 如果请求头中包含UUID
            // 使用现有的UUID保存验证码到Redis（有效期60秒）
            setResult = await redisAPI.setCaptcha(uuidHead, captcha.text)
        }else{          // 如果请求头中没有UUID
            // 生成新的UUID并设置到cookie中
            const id = uuidv4();
            console.log("🆕 生成新的UUID:", id);
            res.cookie("uuid", id, {
                httpOnly: false,    // 设为false以便前端JavaScript可以读取
                secure: false,      // 开发环境设为false，生产环境建议设为true
                sameSite: 'lax',    // 允许跨站请求携带cookie
                maxAge: 60000,      // 60秒过期
                path: '/'           // 设置cookie路径
            });     // 将UUID保存到cookie，用于后续验证
            console.log("🍪 已设置cookie: uuid =", id);
            setResult = await redisAPI.setCaptcha(id, captcha.text)
        }

        // 检查验证码是否成功保存到Redis
        if (!setResult.success) {
            return res.status(500).json({
                code: STATUS_CODES.CAPTCHA_SAVE_FAILED.code,      // 30002: 验证码保存失败
                message: STATUS_CODES.CAPTCHA_SAVE_FAILED.message   // 验证码保存失败
            });
        }

        // 返回SVG格式的验证码图片给客户端
        res.type('svg');                // 设置响应内容类型为SVG
        res.status(200).send(captcha.data);  // 发送验证码图片数据
    } catch (error) {
        // 捕获异常并记录错误日志
        console.error('生成验证码失败:', error.message, error.stack);
        // 返回生成失败的状态码
        res.status(500).json({
            code: STATUS_CODES.CAPTCHA_GENERATE_FAILED.code,      // 30003: 验证码生成失败
            message: STATUS_CODES.CAPTCHA_GENERATE_FAILED.message   // 验证码生成失败
        });
    }
});

// 定义用户登录路由 - POST /sign-in
// 处理用户登录请求，包括邮箱密码验证和图形验证码验证
router.post("/sign-in",
    emailValidator.validateEmail,  // 使用邮箱验证中间件验证邮箱格式
    async (req,res)=>{
        // 1. 从前端表单数据中获取登录信息：邮箱、密码、图形验证码
        const {mail,pass,code} = req.body;

        // 2. 检查邮箱是否已被注册（如果邮箱不存在则无法登录）
        const verifyResult = await userinfosAPI.verifyEmail(mail);
        
        if(!verifyResult.success){  // 如果邮箱不存在（未被注册）
            return res.json({
                code: STATUS_CODES.EMAIL_OR_PASSWORD_ERROR.code,      // 10002: 邮箱或密码错误
                message: STATUS_CODES.EMAIL_OR_PASSWORD_ERROR.message
            })
        }

        // 3. 验证邮箱和密码是否匹配 - 使用封装的密码验证功能
        const userResult = await userinfosAPI.selectUser(mail, pass);

        if(!userResult.success){  // 如果密码验证失败
            return res.json({
                code: STATUS_CODES.EMAIL_OR_PASSWORD_ERROR.code,      // 10002: 邮箱或密码错误
                message: userResult.message                           // 返回具体的错误消息
            })
        }
        
        // 获取验证通过的用户信息
        const user = userResult.message;

        // 4. 验证图形验证码
        const uuid = req.cookies.uuid;  // 从cookie中获取UUID
        if(!uuid){  // 如果UUID不存在
            return res.json({
                code: STATUS_CODES.CAPTCHA_ERROR.code,      // 10003: 验证码输入有误
                message: STATUS_CODES.CAPTCHA_ERROR.message
            })
        }

        // 从Redis中获取保存的验证码并进行比对（忽略大小写）
        const redisCodeResult = await redisAPI.getCaptcha(uuid);
        // if(!redisCodeResult.success || code.toLowerCase() !== redisCodeResult.message.toLowerCase()){
        if(!redisCodeResult.success){  // 如果验证码错误（忽略大小写）
            return res.json({
                code: STATUS_CODES.CAPTCHA_ERROR.code,        // 10003: 验证码输入有误
                message: STATUS_CODES.CAPTCHA_ERROR.message   // 对应的消息文本
            })
        }

        // 5. 登录验证全部通过，生成令牌
        // 生成刷新令牌（长令牌），使用随机UUID确保安全性
        const refreshToken = uuidv4();

        // 将刷新令牌保存到Redis中，用于后续验证
        const setTokenResult = await redisAPI.setRefreshToken(refreshToken);

        if (!setTokenResult.success) {  // 如果保存失败
            return res.json({
                code: STATUS_CODES.SERVER_LOGIN_ERROR.code,      // 50001: 服务器登录错误
                message: STATUS_CODES.SERVER_LOGIN_ERROR.message   // 对应的消息文本
            });
        }

        // 将刷新令牌添加到用户信息中，准备生成访问令牌
        user.refreshToken = refreshToken;

        // 生成访问令牌（短令牌），有效期30分钟
        const token = jwt.sign(user, config.login.accessTokenPrivateKey, {expiresIn: "30m"})

        // 从用户信息中删除刷新令牌，避免敏感信息泄露
        delete user.refreshToken;

        // 清理Redis中的验证码，防止重复使用
        await redisAPI.deleteCaptcha(uuid);

        // 返回登录成功的响应，包含访问令牌和用户信息
        res.json({
            code: STATUS_CODES.SUCCESS.code,       // 0: 操作成功
            message: "登录成功",                     // 自定义成功消息
            data : {                                // 返回的数据对象
                token : token,                      // 访问令牌
                user: {                             // 用户基本信息
                    id: user.id,                    // 用户ID
                    email: user.email,              // 用户邮箱
                    avatar: user.avatar             // 用户头像
                }
            }
        })
    })

// 定义自动登录路由 - POST /auto-login
// 用于验证用户令牌并自动登录，支持令牌续签功能
router.post("/auto-login",async (req, res)=>{
    // 1. 从请求头中获取授权令牌（Authorization）
    const token = req.get("Authorization");

    // 2. 验证访问令牌（短令牌）
    try{
        // 使用JWT验证令牌的有效性
        const user = jwt.verify(token, config.login.accessTokenPrivateKey);

        // 令牌有效，返回用户信息
        res.json({
            code: STATUS_CODES.SUCCESS.code,      // 0: 操作成功
            message: "自动登录成功",                 // 自定义成功消息
            data :user                           // 返回用户对象
        })

    }catch(err){  // 如果访问令牌过期或无效
       // 从失效的访问令牌中解析用户信息和刷新令牌
        const userTemp = jwt.decode(token); // 从失效的短token中解析对象（包含iat、exp等）
        
        // 检查解析结果是否有效
        if (!userTemp || !userTemp.refreshToken) {
            return res.json({
                code: STATUS_CODES.AUTO_LOGIN_FAILED.code,
                message: "令牌无效，请重新登录"
            });
        }
        
        const refreshToken = userTemp.refreshToken;  // 获取刷新令牌（长令牌）

        try {
            // 检查刷新令牌是否存在于Redis中（验证其有效性）
            const result = await redisAPI.isExists(refreshToken);

            if(result.success && result.message){// 如果刷新令牌存在且有效

                // 重新构建用户对象，提取必要信息
                const user = {
                    id : userTemp.id,            // 用户ID
                    email : userTemp.email,      // 用户邮箱
                    avatar : userTemp.avatar,    // 用户头像
                    refersh_token : userTemp.refersh_token  // 刷新令牌
                }

                // 生成新的访问令牌（短令牌），有效期5秒
                const token = jwt.sign(user, config.login.accessTokenPrivateKey, {expiresIn: "30m"})

                // 从用户对象中删除刷新令牌，避免敏感信息泄露
                delete user.refersh_token;

                // 返回令牌续签成功的响应
                return res.json({
                    code: 10000,      // 0: 操作成功
                    message: "自动续签成功",                 // 自定义成功消息
                    data : {                                // 返回的数据对象
                        token : token                      // 新的访问令牌
                    }
                })
            }

            // 刷新令牌也已过期，需要重新登录
            res.json({
                code: STATUS_CODES.LOGIN_EXPIRED.code,      // 40001: 登录已过期
                message: STATUS_CODES.LOGIN_EXPIRED.message   // 对应的消息文本
            });
        } catch (redisErr) {  // Redis操作异常
            // 返回自动登录失败的状态码
            return res.json({
                code: STATUS_CODES.AUTO_LOGIN_FAILED.code,      // 50001: 自动登录失败
                message: STATUS_CODES.AUTO_LOGIN_FAILED.message   // 对应的消息文本
            });
        }
    }
})

// 定义获取用户状态路由 - GET /user/:id/status
// 用于检查指定用户的存在状态和基本信息
router.get("/user/:id/status", async (req, res) => {
    try {
        // 从URL路径参数中获取用户ID
        const userId = req.params.id;
        
        // 调用用户信息API检查用户状态
        const status = await userinfosAPI.checkUserStatus(userId);
        
        // 检查API调用是否成功
        if (!status.success) {
            // 如果API调用失败，返回服务器错误
            return res.json({
                code: STATUS_CODES.SERVER_ERROR.code,      // 50001: 服务器错误
                message: status.message                    // 返回具体的错误消息
            });
        }
        
        // 检查用户是否存在
        if (!status.message.exists) {
            // 如果用户不存在，返回用户未找到错误
            return res.json({
                code: STATUS_CODES.USER_NOT_FOUND.code,      // 60001: 用户未找到
                message: STATUS_CODES.USER_NOT_FOUND.message   // 对应的消息文本
            });
        }
        
        // 用户存在且状态正常，返回成功响应
        res.json({
            code: STATUS_CODES.SUCCESS.code,      // 0: 操作成功
            message: "获取用户状态成功",               // 自定义成功消息
            data: status.message                  // 返回用户状态信息
        });
    } catch (error) {
        // 捕获异常，返回获取用户状态失败错误
            res.json({
                code: STATUS_CODES.USER_STATUS_FAILED.code,      // 60001: 获取用户状态失败
                message: STATUS_CODES.USER_STATUS_FAILED.message   // 对应的消息文本
            });
    }
});

// 定义更新用户资料路由 - PUT /user/:id/profile
// 用于更新指定用户的基本资料信息
router.put("/user/:id/profile", async (req, res) => {
    try {
        // 从URL路径参数中获取用户ID
        const userId = req.params.id;
        // 从前端表单数据中获取要更新的用户资料
        const updateData = req.body;
        
        // 调用用户信息API更新用户资料
        const updatedUser = await userinfosAPI.updateUserProfile(userId, updateData);
        
        // 检查更新操作是否成功
        if (!updatedUser.success) {
            // 如果更新失败，返回服务器错误
            return res.json({
                code: STATUS_CODES.SERVER_ERROR.code,      // 50001: 服务器错误
                message: updatedUser.message               // 返回具体的错误消息
            });
        }
        
        // 更新成功，返回成功响应
        res.json({
            code: STATUS_CODES.SUCCESS.code,      // 0: 操作成功
            message: "更新用户资料成功",               // 自定义成功消息
            data: updatedUser.message              // 返回更新后的用户信息
        });
    } catch (error) {
        // 捕获异常，返回更新用户资料失败错误
            res.json({
                code: STATUS_CODES.UPDATE_PROFILE_FAILED.code,      // 60001: 更新用户资料失败
                message: STATUS_CODES.UPDATE_PROFILE_FAILED.message   // 对应的消息文本
            });
    }
});

// 定义获取用户基本信息路由 - GET /user/:id/info
// 用于获取指定用户的基本信息（如邮箱、头像等）
router.get("/user/:id/info", async (req, res) => {
    try {
        // 从URL路径参数中获取用户ID
        const userId = req.params.id;
        
        // 调用用户信息API获取用户基本信息
        const userInfo = await userinfosAPI.getUserBasicInfo(userId);
        
        // 检查API调用是否成功
        if (!userInfo.success) {
            // 如果获取失败，返回服务器错误
            return res.json({
                code: STATUS_CODES.SERVER_ERROR.code,      // 50001: 服务器错误
                message: userInfo.message                   // 返回具体的错误消息
            });
        }
        
        // 获取成功，返回用户基本信息
        res.json({
            code: STATUS_CODES.SUCCESS.code,      // 0: 操作成功
            message: "获取用户信息成功",               // 自定义成功消息
            data: userInfo.message                // 返回用户基本信息
        });
    } catch (error) {
        // 捕获异常，返回获取用户信息失败错误
        res.json({
            code: STATUS_CODES.GET_USER_INFO_FAILED.code,      // 60001: 获取用户信息失败
            message: STATUS_CODES.GET_USER_INFO_FAILED.message   // 对应的消息文本
        });
    }
});






// 导出路由模块，供其他模块使用
module.exports = router;